/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.yonsei.iwb.sdt.ontology;

import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;

import java.util.*;
import edu.yonsei.iwb.sdt.util.SDTLog;

/**
 *
 * @author OnlyJiny
 */
public class Normalization {

    private static final double Z = 1.645;

    /**
     * 선호 리소스의 Count 수를 바탕으로 정규화된 Weight 산출
     * @param records
     * @return 
     */
    public static ResourceWeights normalizePreferedResourceByMinMax(Hashtable<Resource, Integer> records) {
        ResourceWeights result = new ResourceWeights();
        double min = 1.0;
        double max = 0.0;
        double a = 0.0;
        double b = 0.0;
        Enumeration<Resource> keys = records.keys();
        while (keys.hasMoreElements()) {
            Resource node = keys.nextElement();
            double value = records.get(node);
            if(value > max)
                max = value;
            if(value < min)
                min = value;
        }
        a = (-0.8) / (min - max);
        b = 0.9 - (a * max);
        keys = records.keys();
        while (keys.hasMoreElements()) {
            Resource node = keys.nextElement();
            double value = records.get(node);
            result.put(node, (a * value) + b);
        }
        return result;
    }
    
    /**
     * normalize weights from 0 to 1
     * @param records
     * @return 
     */
    public static ResourceWeights normalizeByMinMax(ResourceWeights records) {
        ResourceWeights result = new ResourceWeights();
        double min = 1.0;
        double max = 0.0;
        
        Enumeration<Resource> keys = records.keys();
        while (keys.hasMoreElements()) {
            Resource node = keys.nextElement();
            double value = records.get(node);
            if(value > max)
                max = value;
            if(value < min)
                min = value;
        }
        
        keys = records.keys();
        while (keys.hasMoreElements()) {
            Resource node = keys.nextElement();
            double value = records.get(node);
            double weight = ((value-min)/(max-min));
            SDTLog.log(SDTLog.DETAIL, "# \"" + node+"\" ,  " +  weight +"\n");            
            result.put(node, weight);
        }
        return result;
    }
    
    public static ResourceWeights normalize(ResourceWeights records) {
        ResourceWeights result = new ResourceWeights();
        double average = MathFunction.average(records.elements());
        double deviation = MathFunction.deviation(records.elements(), average);
        double x = Normalization.getX(average, deviation);
        double slope = Normalization.getSlope(average, x);
        Enumeration<Resource> keys = records.keys();
        while (keys.hasMoreElements()) {
            Resource node = keys.nextElement();
            double value = records.get(node);
            result.put(node, MathFunction.sigmoid(value, average, slope));
        }
        return result;
    }

    private static double getX(double average, double deviation) {
        return ((deviation * Z) + average);
    }

    private static double getSlope(double average, double x) {
        if (average == x) {
            return 1;
        } else {
            return (2.197225 / (x - average));
        }
    }
}
